package com.hemerasolutions.v2trainer.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.hemerasolutions.v2trainer.dao.ExceptionDao;
import com.hemerasolutions.v2trainer.dao.interfaces.BodyRegionDaoInterface;
import com.hemerasolutions.v2trainer.dao.interfaces.ExerciseDaoInterface;
import com.hemerasolutions.v2trainer.dao.interfaces.ExerciseGroupDaoInterface;
import com.hemerasolutions.v2trainer.dao.interfaces.TrainingTypeDaoInterface;
import com.hemerasolutions.v2trainer.dao.interfaces.VersionableExerciseGroupDaoInterface;
import com.hemerasolutions.v2trainer.model.exercise.Exercise;
import com.hemerasolutions.v2trainer.model.exerciseGroup.ExerciseGroup;
import com.hemerasolutions.v2trainer.model.exerciseGroup.VersionableExerciseGroup;
import com.hemerasolutions.v2trainer.model.library.Library;
import com.hemerasolutions.v2trainer.model.muscle.BodyRegion;
import com.hemerasolutions.v2trainer.model.training.TrainingType;
import com.hemerasolutions.v2trainer.service.interfaces.ExerciseGroupServiceInterface;


@Service("exerciseGroupService")
public class ExerciseGroupService extends BaseService implements ExerciseGroupServiceInterface {

	private static final long serialVersionUID = 1L;

	@Autowired
	private ExerciseGroupDaoInterface exerciseGroupDao;

	@Autowired 
	private VersionableExerciseGroupDaoInterface vExerciseGroupDao;
	
	@Autowired
	private TrainingTypeDaoInterface ttDao;
	
	@Autowired
	private BodyRegionDaoInterface brDao;

	@Autowired
	private ExerciseDaoInterface exerciseDao;
	
	public ExerciseGroupService() {
		super();
	}

	@PostConstruct
	public void init(){
	}
	
	@Override
	public List<TrainingType> listTrainingType(){
		return ttDao.list();
	}

	@Override
	public List<BodyRegion> listBodyRegion(){
		return brDao.list();
	}
	
	@Override
	public List<VersionableExerciseGroup> findExerciseGroups(Map<String, Object> fields,
			List<Library> librarys) {

		List<VersionableExerciseGroup> vExerciseGroups = new ArrayList<VersionableExerciseGroup>();
		
		for(Library library:librarys){
			
			for(VersionableExerciseGroup vExerciseGroup :library.getVersionableExerciseGroups()){
				for(ExerciseGroup exerciseGroup : vExerciseGroup.getExerciseGroupVersions()){
					if(this.exerciseGroupMatch(exerciseGroup, fields)){
						if(!vExerciseGroups.contains(vExerciseGroup)){
							vExerciseGroups.add(vExerciseGroup);
						}
					}
				}				
			}
			

		}
			
		return vExerciseGroups;
	}
	
	@Override
	public List<ExerciseGroup> filterExerciseGroups(Map<String, Object> fields,
			List<ExerciseGroup> exerciseGroups) {

		
		List<ExerciseGroup> result = new ArrayList<ExerciseGroup>();
		
		
		for(ExerciseGroup exerciseGroup:exerciseGroups){
			if(this.exerciseGroupMatch(exerciseGroup,fields)){
				result.add(exerciseGroup);
			}
		}
		
		return result;
	}


	private boolean exerciseGroupMatch(ExerciseGroup exerciseGroup,
			Map<String, Object> fields) {

		Calendar cal1 = Calendar.getInstance();
		Calendar cal2 = Calendar.getInstance();

		if(fields.containsKey("name")){
			if(! exerciseGroup.getName().toUpperCase().contains(((String)fields.get("name")).toUpperCase())){
				return false;
			}
		}
		
		if(fields.containsKey("obs")){
			if(! exerciseGroup.getName().toUpperCase().contains(((String)fields.get("name")).toUpperCase())){
				return false;
			}
		}

		if(fields.containsKey("description")){
			if(! exerciseGroup.getName().toUpperCase().contains(((String)fields.get("description")).toUpperCase())){
				return false;
			}
		}

		if(fields.containsKey("begCreatedAt")){

			cal1.setTime(exerciseGroup.getCreatedAt());
			cal2.setTime((Date)fields.get("begCreatedAt"));

			if(! (cal1.get(Calendar.YEAR) >= cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) >= cal2.get(Calendar.DAY_OF_YEAR))){
				return false;
			}
		}
			

		if(fields.containsKey("endCreatedAt")){

			cal1.setTime(exerciseGroup.getCreatedAt());
			cal2.setTime((Date)fields.get("endCreatedAt"));

			if(! (cal1.get(Calendar.YEAR) <= cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) <= cal2.get(Calendar.DAY_OF_YEAR))){
				return false;
			}			
		}
		
		if(fields.containsKey("begChangedAt")){
			cal1.setTime(exerciseGroup.getCreatedAt());
			cal2.setTime((Date)fields.get("begChangedAt"));

			if(! (cal1.get(Calendar.YEAR) >= cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) >= cal2.get(Calendar.DAY_OF_YEAR))){
				return false;
			}
			
		}

		if(fields.containsKey("endChangedAt")){

			cal1.setTime(exerciseGroup.getCreatedAt());
			cal2.setTime((Date)fields.get("endChangedAt"));

			if(! (cal1.get(Calendar.YEAR) <= cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) <= cal2.get(Calendar.DAY_OF_YEAR))){
				return false;
			}						
		}

		
		return true;
	}


	@Override
	public List<ExerciseGroup> searchExerciseGroups(Map<String, Object> fields) {

		return exerciseGroupDao.searchExerciseGroups(fields);
			
	}


	@Override
	public ExerciseGroup createExerciseGroup(ExerciseGroup exerciseGroup) throws ExceptionService {
		try {
			exerciseGroup = exerciseGroupDao.create(exerciseGroup);
		} catch (ExceptionDao e) {
			e.printStackTrace();
			throw new ExceptionService(e);
		} catch (ExceptionService e) {
			throw e;
		}
	
	return exerciseGroup;
		
	}


	@Override
	public VersionableExerciseGroup saveVersionableExerciseGroup(VersionableExerciseGroup versionableExerciseGroup) throws ExceptionService {
		try {
			versionableExerciseGroup = vExerciseGroupDao.save(versionableExerciseGroup);
		} catch (ExceptionDao e) {
			e.printStackTrace();
			throw new ExceptionService(e);
		} catch (ExceptionService e) {
			throw e;
		}
	
	return versionableExerciseGroup;
		
	}


	@Override
	public void deleteVersionableExerciseGroup(VersionableExerciseGroup versionableExerciseGroup) throws ExceptionService {
		try {
			vExerciseGroupDao.delete(versionableExerciseGroup);
		} catch (ExceptionDao e) {
			e.printStackTrace();
			throw new ExceptionService(e);
		} catch (ExceptionService e) {
			throw e;
		}
		
	}

	
	@Override
	public VersionableExerciseGroup createVersionableExerciseGroup(VersionableExerciseGroup exerciseGroup) throws ExceptionService {
		try {
			exerciseGroup = vExerciseGroupDao.create(exerciseGroup);
		} catch (ExceptionDao e) {
			e.printStackTrace();
			throw new ExceptionService(e);
		} catch (ExceptionService e) {
			throw e;
		}
	
	return exerciseGroup;
		
	}


	@Override
	public ExerciseGroup saveExerciseGroup(ExerciseGroup exerciseGroup) throws ExceptionService {
		try {
			exerciseGroup = exerciseGroupDao.save(exerciseGroup);
		} catch (ExceptionDao e) {
			e.printStackTrace();
			throw new ExceptionService(e);
		} catch (ExceptionService e) {
			throw e;
		}
	
	return exerciseGroup;
		
	}


	@Override
	public void deleteExerciseGroup(ExerciseGroup exerciseGroup) throws ExceptionService {
		try {
			exerciseGroupDao.delete(exerciseGroup);
		} catch (ExceptionDao e) {
			e.printStackTrace();
			throw new ExceptionService(e);
		} catch (ExceptionService e) {
			throw e;
		}
		
	}
	
	

	@Override
	public ExerciseGroup readExerciseGroup(ExerciseGroup exerciseGroup) {
		return exerciseGroupDao.getById(exerciseGroup.getId());
	}

	@Override
	public List<Exercise> searchExercises(Map<String, Object> fields) {
		return exerciseDao.search(fields);
	}

	@Override
	public List<VersionableExerciseGroup> searchVersionableExerciseGroups(
			Map<String, Object> fields) {
		
		return vExerciseGroupDao.searchVersionableExerciseGroups(fields);
	}


	



}
